package com.AICoupon.utils;

import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.connection.RedisConnection;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.concurrent.atomic.AtomicBoolean;

/**
 * Redis连接健康检查器
 * 定期检查Redis连接状态，并在连接异常时尝试恢复
 */
@Slf4j
@Component
public class RedisConnectionHealthChecker {

    @Resource
    private StringRedisTemplate stringRedisTemplate;
    
    private final AtomicBoolean connectionHealthy = new AtomicBoolean(true);
    private int consecutiveFailures = 0;
    private static final int MAX_FAILURES = 3;
    private static final String HEALTH_CHECK_KEY = "health:check:redis";
    
    /**
     * 每30秒执行一次健康检查
     */
    @Scheduled(fixedRate = 30000)
    public void checkConnection() {
        try {
            // 执行简单的Redis操作来检查连接
            stringRedisTemplate.opsForValue().set(HEALTH_CHECK_KEY, String.valueOf(System.currentTimeMillis()), java.time.Duration.ofSeconds(60));
            
            // 如果成功，重置失败计数并更新状态
            if (!connectionHealthy.get()) {
                log.info("Redis连接已恢复正常");
                connectionHealthy.set(true);
            }
            consecutiveFailures = 0;
            
        } catch (Exception e) {
            handleConnectionFailure(e);
        }
    }
    
    /**
     * 处理连接失败情况
     */
    private void handleConnectionFailure(Exception e) {
        consecutiveFailures++;
        connectionHealthy.set(false);
        
        log.error("Redis连接健康检查失败，连续失败次数: {}/{}", consecutiveFailures, MAX_FAILURES, e);
        
        if (consecutiveFailures >= MAX_FAILURES) {
            log.warn("Redis连接持续失败，尝试重新初始化连接...");
            tryReconnect();
        }
    }
    
    /**
     * 尝试重新建立Redis连接
     */
    private void tryReconnect() {
        try {
            RedisConnectionFactory factory = stringRedisTemplate.getConnectionFactory();
            if (factory != null) {
                // 获取并立即关闭连接，强制下次获取时创建新连接
                RedisConnection connection = factory.getConnection();
                if (connection != null) {
                    connection.close();
                    log.info("已关闭现有Redis连接，等待重新建立");
                }
            }
            
            // 测试新连接
            stringRedisTemplate.opsForValue().get("test:reconnect");
            log.info("Redis连接重新建立成功");
            consecutiveFailures = 0;
            connectionHealthy.set(true);
            
        } catch (Exception e) {
            log.error("尝试重新建立Redis连接失败", e);
        }
    }
    
    /**
     * 检查当前Redis连接是否健康
     * @return 连接健康状态
     */
    public boolean isConnectionHealthy() {
        return connectionHealthy.get();
    }
    
    /**
     * 手动触发连接检查
     * @return 检查后的连接状态
     */
    public boolean checkConnectionManually() {
        checkConnection();
        return connectionHealthy.get();
    }
}